package com.small.sentinel.slots.block.degrade;

import com.small.sentinel.slots.block.AbstractRule;
import com.small.sentinel.slots.block.RuleConstant;

import java.util.Objects;

public class DegradeRule extends AbstractRule {

    public DegradeRule() {}

    public DegradeRule(String resourceName) {
        setResource(resourceName);
    }

    /**
     * 熔断策略 0-慢调用比率 1-异常率 2-异常数
     */
    private int grade = RuleConstant.DEGRADE_GRADE_RT;

    /**
     * 当grade = 慢调用比率 时，阈值=最大rt
     * 当grade = 异常率 时，阈值=异常率
     * 当grade = 异常数 时，阈值=异常数
     */
    private double count;

    /**
     * 熔断时长（秒）：断路器 从 开放 变为 半开 的时长
     */
    private int timeWindow;

    /**
     * 最少请求数 ---> 断路器起效 默认5
     */
    private int minRequestAmount = RuleConstant.DEGRADE_DEFAULT_MIN_REQUEST_AMOUNT;

    /**
     * 使用grade=慢调用比率时，代表慢调用比率的阈值
     */
    private double slowRatioThreshold = 1.0d;

    /**
     * 统计时长（毫秒）--- 时间窗口大小
     */
    private int statIntervalMs = 1000;

    public int getGrade() {
        return grade;
    }

    public DegradeRule setGrade(int grade) {
        this.grade = grade;
        return this;
    }

    public double getCount() {
        return count;
    }

    public DegradeRule setCount(double count) {
        this.count = count;
        return this;
    }

    public int getTimeWindow() {
        return timeWindow;
    }

    public DegradeRule setTimeWindow(int timeWindow) {
        this.timeWindow = timeWindow;
        return this;
    }

    public int getMinRequestAmount() {
        return minRequestAmount;
    }

    public DegradeRule setMinRequestAmount(int minRequestAmount) {
        this.minRequestAmount = minRequestAmount;
        return this;
    }

    public double getSlowRatioThreshold() {
        return slowRatioThreshold;
    }

    public DegradeRule setSlowRatioThreshold(double slowRatioThreshold) {
        this.slowRatioThreshold = slowRatioThreshold;
        return this;
    }

    public int getStatIntervalMs() {
        return statIntervalMs;
    }

    public DegradeRule setStatIntervalMs(int statIntervalMs) {
        this.statIntervalMs = statIntervalMs;
        return this;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) { return true; }
        if (o == null || getClass() != o.getClass()) { return false; }
        if (!super.equals(o)) { return false; }
        DegradeRule rule = (DegradeRule)o;
        return Double.compare(rule.count, count) == 0 &&
                timeWindow == rule.timeWindow &&
                grade == rule.grade &&
                minRequestAmount == rule.minRequestAmount &&
                Double.compare(rule.slowRatioThreshold, slowRatioThreshold) == 0 &&
                statIntervalMs == rule.statIntervalMs;
    }

    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), count, timeWindow, grade, minRequestAmount,
                slowRatioThreshold, statIntervalMs);
    }

    @Override
    public String toString() {
        return "DegradeRule{" +
                "resource=" + getResource() +
                ", grade=" + grade +
                ", count=" + count +
                ", limitApp=" + getLimitApp() +
                ", timeWindow=" + timeWindow +
                ", minRequestAmount=" + minRequestAmount +
                ", slowRatioThreshold=" + slowRatioThreshold +
                ", statIntervalMs=" + statIntervalMs +
                '}';
    }
}
